package com.agou.ssh.core.db.field;

import java.io.Serializable;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.apache.commons.lang.builder.HashCodeBuilder;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.UserType;

import com.agou.core.ss.SSTrace;
import com.agou.core.util.UtDate;

public class DateField implements UserType, Serializable {

	private static final long serialVersionUID = -8220824205498471385L;
	private static SSTrace ssTrace = SSTrace.getInstance(DateField.class);
	
	private static final int[] SQL_TYPES={Types.DATE};
	public UtDate uDate = null;//new UtDate();
	
	public  DateField(){
		uDate = new UtDate();
	}
	
	public  DateField(Date date){
		uDate = new UtDate(date);
	}

	@Override
	public Object assemble(Serializable arg0, Object arg1) throws HibernateException {
		ssTrace.error("assemble", "parameter1:#0,parameter2:#1, ", arg0, arg1);
		return null;
	}

	/**
	  * 提供自定义类型的完全复制方法
	  * 本方法将用构造返回对象
	  * 当nullSafeGet方法调用之后，我们获得了自定义数据对象，在向用户返回自定义数据之前，
	  * deepCopy方法将被调用，它将根据自定义数据对象构造一个完全拷贝，并将此拷贝返回给用户
	  * 此时我们就得到了自定义数据对象的两个版本，第一个是从数据库读出的原始版本，其二是我们通过
	  * deepCopy方法构造的复制版本，原始的版本将有Hibernate维护，复制版由用户使用。原始版本用作
	  * 稍后的脏数据检查依据；Hibernate将在脏数据检查过程中将两个版本的数据进行对比（通过调用
	  * equals方法），如果数据发生了变化（equals方法返回false），则执行对应的持久化操作
	  * 
	  * @param value
	  * @return
	  * @throws HibernateException
	  */
	public Object deepCopy(Object value) throws HibernateException {
		return value;
	}

	@Override
	public Serializable disassemble(Object arg0) throws HibernateException {
		ssTrace.error("disassemble", "parameter1:#0 ", arg0);
		return null;
	}

	/**
	  * 自定义数据类型的比对方法
	  * 此方法将用作脏数据检查，参数x、y分别为数据的两个副本
	  * 如果equals方法返回false,则Hibernate将认为数据发生变化,并将变化更新到数据库表中
	  * @param x
	  * @param y
	  * @return
	  * @throws HibernateException
	  */
	public boolean equals(Object value1, Object value2) throws HibernateException {
		if(value1 == value2){
			return true;
		}
		if(value1 == null || value2 == null){
			return false;
		}
		DateField date1 = (DateField)value1;
		DateField date2 = (DateField)value2;
		if(date1.getTimeInMillis() == date2.getTimeInMillis() ){
			return true;
		}
		return false;
	}
	
	/* 得到hash码 */
	public int hashCode(Object arg0) throws HibernateException {
		ssTrace.error("hashCode", "parameter1:#0", arg0);
		return new HashCodeBuilder().append(arg0).toHashCode();
	}

	/**
	  * 本类型实例是否可变
	  * @return
	  */
	public boolean isMutable() {
		//ssTrace.error("isMutable", "start...");
		return false;
	}

	/**
	  * 从JDBC ResultSet读取数据,将其转换为自定义类型后返回
	  * (此方法要求对克能出现null值进行处理)
	  * names中包含了当前自定义类型的映射字段名称
	  * @param rs
	  * @param names
	  * @param owner
	  * @return
	  * @throws HibernateException
	  * @throws SQLException
	  */
	public Object nullSafeGet(ResultSet rs, String[] names,SessionImplementor session, Object value) throws HibernateException,
			SQLException {
		//ssTrace.error("nullSafeGet", "start...");
		Date sqlDate = rs.getDate(names[0]);
		//DateField DateField= new DateField(sqlDate);
		return new DateField(sqlDate);
//		
//		
//		if(names != null){
//			for(int i = 0 ; i < names.length ; i++){
//				System.out.println("names["+i+"] = " + names[i]);
//			}
//		}else{
//			System.out.println("names is null");
//		}
//		
//		System.out.println("values = " + value);
//		System.out.println();
//		return null;
	}

	 /**
	  * 本方法将在Hibernate进行数据保存时被调用
	  * 我们可以通过PreparedStateme将自定义数据写入到对应的数据库表字段
	  * @param st
	  * @param value
	  * @param index
	  * @throws HibernateException
	  * @throws SQLException
	  */
	public void nullSafeSet(PreparedStatement ps, Object value, int index,SessionImplementor session) throws HibernateException, SQLException {
		//ssTrace.error("nullSafeSet2", "start...");
		//System.out.println("index = " + index);
		//System.out.println("value = " + value);
		Date sqlDate = new Date(((DateField)value).getTimeInMillis());
		ps.setDate(index, sqlDate);
	}

	@Override
	public Object replace(Object arg0, Object arg1, Object arg2)
			throws HibernateException {
		ssTrace.error("replace", "start...");
		return null;
	}

	/**
	  * UserType.nullSafeGet()所返回的自定义数据类型
	  * @return
	  */
	public Class<DateField> returnedClass() {
		return DateField.class;
	}
	
	
	/**
	  * 返回UserType所映射字段的SQL类型（java.sql.Types)
	  * 返回类型为int[]，其中包含了映射个字段的SQL类型代码
	  * (UserType可以映射到一个或者多个字段)
	  * @return
	  */
	public int[] sqlTypes() {
		return SQL_TYPES;
	}

	public long getTimeInMillis(){
		return uDate.getTimeInMillis();
	}
	
	public String toString(){
		return uDate.toString();
	}
	
	public String format(){
		return uDate.formatDate();
	}
}